﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Ionic.Zip;
using XemlUtilities.ISA.Protocol;
using XemlUtilities.ISA.Ontology;
using XemlUtilities.DataSet;

namespace XemlUtilities.ISA
{
    public class IsaExporter : IDisposable
    {
        internal const string multipleValueDelimiter = ";";
        internal const string multipleFieldDelimiter = "\t";
        internal const string fieldEncapsulater = "\"";

        static Dictionary<string, string> chromatogramFiles;

        Guid _xemlId;
        string _connectionstring;

        #region constructors
        public IsaExporter(Guid xemlId, string connectionstring)
        {
            _xemlId = xemlId;
            _connectionstring = connectionstring;
            OntologyBase.ConnectionString = connectionstring;
            chromatogramFiles = new Dictionary<string, string>();
        }
        #endregion constructors

        public static List<String> Encapsulate(List<String> l)
        {
            return Encapsulate(fieldEncapsulater, l);
        }

        public static List<String> Encapsulate(String encap_char, List<String> l)
        {
            for (int i = 0; i < l.Count; i++)
            {
                l[i] = String.Concat(encap_char, Escape(l[i]), encap_char);
            }
            return l;
        }

        public static String Encapsulate(String s)
        {
            return String.Concat(fieldEncapsulater, Escape(s), fieldEncapsulater);
        }

        public static String[] Encapsulate(params String[] l)
        {
            return Encapsulate(fieldEncapsulater, l);
        }

        public static String[] Encapsulate(String encap_char, params String[] l)
        {
            // eventhough section 4 of the ISA RC Spec file doesn't really specify how to handle escaping of quotation marks!
            for (int i = 0; i < l.Length; i++)
            {
                l[i] = String.Concat(encap_char, Escape(l[i]), encap_char);
            }
            return l;
        }

        public static String Escape(String s)
        {
            if (s != null) return s.Replace("\"", ""); // remove quotes alltogether
            return String.Empty;
        }

        public void AddChromatogramFile(String fileName, string path)
        {
            chromatogramFiles.Add(fileName, path);
        }

        public void Write(XemlDataSet xds, Stream outstream)
        {
            if (xds == null)
            {
                throw new ArgumentNullException("ds");
            }
            if (xds.Document.Count != 1)
            {
                throw new Exception("expecting exactly one 'document' record");
            }
            if (xds.SampleMapping.Count == 0)
            {
                throw new Exception("no experimental results mapped to this document");
            }
            if (outstream == null)
            {
                throw new ArgumentNullException("outstream");
            }

            //using (ZipOutputStream oZipStream = new ZipOutputStream(outstream))
            //using(MemoryStream ms = new MemoryStream())
            using (ZipFile zip = new ZipFile())
            {
                ProtocolBase.Init(xds, _xemlId, _connectionstring);
                zip.AddEntry(Study.GetFileName(xds), Study.GetStream(xds));
                zip.AddEntry(Assay.GetFileName(xds), Assay.GetStream(xds, _xemlId, _connectionstring));
                zip.AddEntry(Metabolites.GetFileName(xds), Metabolites.GetStream(_xemlId, _connectionstring));
                zip.AddEntry(Investigation.GetFileName(xds), Investigation.GetStream(xds, _xemlId, _connectionstring));
                zip.AddEntry("TagFinderSettings.txt", TagFinder.GetStream(_xemlId, _connectionstring));
                zip.AddEntry("readme.txt", GetReadme(xds, _xemlId));
                zip.AddEntry(string.Concat(xds.Document.Single().PutativeFileName, ".xeml"), xds.Document.Single().Xeml);

                //zip.AddEntry("nadine.txt", new FileStream(@"D:\jahu\Nadine\rt found.txt", FileMode.Open, FileAccess.Read));

                foreach (var item in xds.SampleMapping.GetChromatograms())
                {
                    if (chromatogramFiles.ContainsKey(item.Value))
                    {
                        zip.AddEntry(new FileInfo(item.Value).Name, File.Open(chromatogramFiles[item.Value], FileMode.Open));
                    }
                    else
                    {
                        zip.AddEntry(item.Value, GetEmptyFile());
                    }
                }

                zip.Save(outstream);
                //ms.CopyTo(outstream);
                //return ms.Position;
            }
        }

        private static MemoryStream GetEmptyFile()
        {
            return new MemoryStream(Encoding.UTF8.GetBytes("File content will be made promptly available to the public upon request to kopka@mpimp-golm.mpg.de ."));
        }

        private static MemoryStream GetReadme(XemlDataSet xds, Guid xemlId)
        {
            MemoryStream s = new MemoryStream();
            System.IO.StreamWriter txtWriter = new System.IO.StreamWriter(s);
            txtWriter.WriteLine("title:\t{0}", xds.Document.Single().Name);
            txtWriter.WriteLine("exported:\t{0}", DateTime.Now.ToString());
            txtWriter.WriteLine("link:\t{0}", string.Format("http://gmd.mpimp-golm.mpg.de/profile/default.aspx?XemlId={0}", xemlId));

            txtWriter.Flush();
            s.Seek(0, SeekOrigin.Begin);
            return s;
        }

        public virtual void Dispose()
        {
        }
    }
}
